home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / lib / extra / muldiv.a < prev    next >
Text File  |  1994-02-01  |  3KB  |  126 lines

  1.  
  2.         ;    MULDIV.A
  3.         ;
  4.         ;    (c)Copyright 1990, Matthew Dillon, All Rights Reserved
  5.         ;
  6.         ;    r = MulDiv(a,b,c)   long a,b,c;
  7.         ;    r = MulDivU(a,b,c)  unsigned long a,b,c;
  8.         ;
  9.         ;    result.32 = a.32 * b.32 / c.32
  10.         ;
  11.         ;    32x32->64 64/32->32 multiply-divide combination
  12.  
  13.         section text,CODE
  14.  
  15.         xdef    _MulDiv
  16.         xdef    _MulDivU
  17.         xdef    _hyper_MulDiv
  18.         xdef    _hyper_MulDivU
  19.  
  20. _hyper_MulDiv:
  21. _MulDiv:
  22.         movem.l D2-D4,-(sp) ; save D2/D3 (generic compiler compatibility)
  23.         moveq.l #0,D4    ; clear negate flag
  24.         lea     16(sp),A0   ; address of 'a'
  25.         move.l  A0,A1    ; save A1 for muldivu call
  26.         tst.l   (A0)        ; test a
  27.         bpl     mp
  28.         neg.l   (A0)+       ; n--
  29.         tst.l   (A0)        ; test b
  30.         bpl     mnp
  31.         neg.l   (A0)+       ; nn-
  32.         tst.l   (A0)        ; test c
  33.         bpl     muldivu    ; nnp CALL, RESULT POSITIVE
  34. mppn        neg.l   (A0)        ; nnn
  35. mpnp
  36. mnpp        moveq.l #1,D4    ; set negate flag
  37.         bra     muldivu
  38.  
  39. mp        addq.l  #4,A0    ; p--
  40.         tst.l   (A0)        ; test b
  41.         bpl     mpp
  42.         neg.l   (A0)+       ; pn-
  43.         tst.l   (A0)        ; test c
  44.         bpl     mpnp
  45.         neg.l   (A0)        ; pnn
  46.         bra     muldivu    ; jmp to routine
  47.  
  48. mpp        addq.l  #4,A0    ; pp-
  49.         tst.l   (A0)
  50.         bpl     muldivu    ; ppp RESULT POSITIVE
  51.         bra     mppn       ; RESULT NEGATIVE (negate (A0) befor call)
  52.  
  53. mnp        addq.l  #4,A0    ; np-
  54.         tst.l   (A0)        ; test c
  55.         bpl     mnpp       ; RESULT NEGATIVE
  56.         neg.l   (A0)        ; npn
  57.         bra     muldivu    ; RESULT POSITIVE
  58.  
  59.         ;    MulDivU(a,b,c)          AH 4(sp) AL 6(sp) BH 8(sp) BL 10(sp)
  60.         ;    unsigned long a   @4(sp)
  61.         ;    unsigned long b   @8(sp)
  62.         ;    unsigned long c   @12(sp)
  63.  
  64. _hyper_MulDivU:
  65. _MulDivU:
  66.         movem.l D2-D4,-(sp) ; save D2-D4
  67.         moveq.l #0,D4    ; clear negate flag
  68.         lea     16(sp),A1   ; address of 'a'
  69. muldivu
  70.         lea     4(A1),A0
  71.  
  72.         move.w  (A0)+,D3    ; bh ah     8(sp)  A0 8->10
  73.         mulu.w  (A1)+,D3    ;           4(sp)  A1 4->6
  74.         move.w  (A0),D0     ; bl al    10(sp)  A0 10
  75.         mulu    (A1),D0     ;           6(sp)  A1 6
  76.         move.w  (A0),D1     ; bl ah    10(sp)  A0 10
  77.         mulu.w  -(A1),D1    ;           4(sp)  A1 now 4
  78.         move.w  -(A0),D2    ; bh al     8(sp)  A0 now 8
  79.         mulu.w  -(A0),D2    ;           6(sp)  A0 now 6
  80.         add.l   D1,D2    ; combine blah and bhal
  81.         bcc     mud1
  82.         add.l   #$10000,D3
  83. mud1        swap    D0        ; LSB MSB
  84.         add.w   D2,D0
  85.         swap    D0
  86.         swap    D2
  87.         and.l   #$FFFF,D2
  88.         addx.l  D2,D3    ;64 bit mul result: D3|D0
  89.  
  90.                 ;64 bit by 32 bit division.  32 bit result.
  91.  
  92.         move.l  6(A0),D1    ;D1 = c           A0 WAS 6
  93.         beq     mdfail
  94.  
  95.         sub.l   A0,A0    ;Divide!    D1 into D3|D0, D2 = cntr, A0 = rslt
  96.         move.w  #31,D2    ;(no initial compare).  31 + 1 iterations
  97. mud10        adda.l  A0,A0    ;shift result left
  98.         asl.l   #1,D0    ;Shift left
  99.         roxl.l  #1,D3
  100.         cmp.l   D1,D3
  101.         bcs     mud11      ;if D3  < D1, skip  (blo)
  102.         sub.l   D1,D3    ;   D3 >= D1
  103.         addq.l  #1,A0    ;result = result | 1
  104. mud11        dbf     D2,mud10
  105.  
  106.         ;;     If remainder (D3) larger than 1/2 C (D1 >> 1), then
  107.         ;;     round up result.    REMOVED
  108.         ;
  109.         ;lsr.l   #1,D1
  110.         ;cmp.l   D1,D3
  111.         ;blo     mud12    ; skip if remainder < 1/2C
  112.         ;addq.l  #1,A0
  113. mud12
  114.         move.l  A0,D0    ;return result
  115.         tst.l   D4        ;D4 non-zero means negate result
  116.         beq     mud13
  117.         neg.l   D0
  118. mud13        movem.l (sp)+,D2-D4 ;restore D2-D4
  119.         rts
  120.  
  121. mdfail        moveq.l #-1,D0
  122.         bra     mud13
  123.  
  124.         END
  125.  
  126.